﻿using Microsoft.AspNetCore.Mvc;
using System.Reflection;
using WcMatch.Models;
using WcMatch.Attributes;
using Microsoft.EntityFrameworkCore;
using System.Text.RegularExpressions;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
using Microsoft.AspNetCore.Hosting;
using WcMatch.Consts;
using Microsoft.VisualBasic;
using System.Data.Entity;
using System.Security.AccessControl;
using System.Text.Json.Serialization;
using System.Text.Json.Nodes;
using System.Text.Json;

namespace WcMatch.Controllers
{
    [Route("[controller]/[action]")]
    [ApiController]
    public class CompanyController : ControllerBase
    {
        CompanyContext _compayContext;
        JobContext _jobContext;
        RecruitmentApplicationCxt _raCxt;
        IWebHostEnvironment _webHostEnvironment;
        StuResumeContext _resumeCxt;
        StudentContext _stuCxt;
        UniversityDivisionContext _udCxt;

        public CompanyController(CompanyContext cContext, 
                                 JobContext jobContext, 
                                 RecruitmentApplicationCxt raCxt,
                                 StuResumeContext resumeCxt,
                                 StudentContext stuCxt,
                                 UniversityDivisionContext udCxt,
                                 IWebHostEnvironment webHostEnvironment)
        {
            _compayContext = cContext;
            _jobContext = jobContext;
            _raCxt = raCxt;
            _resumeCxt = resumeCxt;
            _stuCxt = stuCxt;
            _udCxt = udCxt;
            _webHostEnvironment = webHostEnvironment;
        }

        #region 企业信息
        [HttpPost]
        public async Task<IActionResult> Register([FromForm] IFormCollection dict)
        {
            if(dict.Keys.Count() == 0)
                return BadRequest(new ActionStatus(-1, "注册信息不完整")); 
            
            Company c = new Company();
            if(!ParseCompanyForm(ref c, dict))
                return BadRequest(new ActionStatus(-1, "参数异常"));            

            var cs = _compayContext.Companies.Where(s => s.UName == c.UName || s.CompanyId == c.CompanyId || s.Name == c.Name).FirstOrDefault();
            if(cs != null)
                return BadRequest(new ActionStatus(-1, "账号或企业已存在"));

            _compayContext.Add(c);
            int line = await _compayContext.SaveChangesAsync();
            if(line > 0)
                return Ok(new ActionStatus(200,"注册成功，请完善公司信息", c.Uid));
            else
                return BadRequest(new ActionStatus(-1, "内部错误：注册失败"));

        }

        private bool ParseCompanyForm(ref Company company, IFormCollection dict)
        {
            if (dict.Keys.Count == 0)
                return false;
            PropertyInfo[] pis = company.GetType().GetProperties();
            foreach(PropertyInfo pi in pis)
            {
                string name = pi.Name.ToLower();
                if (!dict.ContainsKey(pi.Name))
                    continue;
                var pValue = dict[name][0];
                if (string.IsNullOrEmpty(pValue))
                    continue;
                if (pi.PropertyType.FullName.Contains("DateTime")) 
                {
                    DateTime dt;
                    if (DateTime.TryParse(pValue, out dt))
                        pi.SetValue(company, dt, null);
                    else
                        return false;
                }
                else if(pi.PropertyType.FullName.Contains("Int32"))
                {
                    int v;
                    if(Int32.TryParse(pValue, out v))
                        pi.SetValue(company, v, null);
                    else
                      return false;
                }
                else if (pi.PropertyType.FullName.Contains("String"))
                {
                    pi.SetValue(company, pValue, null);
                }
            }
            if (string.IsNullOrEmpty(company.UName) ||
                string.IsNullOrEmpty(company.Pwd) ||
                string.IsNullOrEmpty(company.CompanyId) ||
                string.IsNullOrEmpty(company.Name))
                return false;
            return true;
        }

        [HttpPost]
        public async Task<IActionResult> Login(string uname, string pwd)
        {
            if (string.IsNullOrEmpty(uname) || string.IsNullOrEmpty(pwd))
                return BadRequest(new ActionStatus(-1, "参数异常"));
            var company = _compayContext.Companies.FirstOrDefault(s => s.UName == uname && s.Pwd == pwd);
            if (company == null)
                return NotFound(new ActionStatus(-1, "用户不存在"));
            return Ok(new ActionStatus(200, "登录成功", company.Uid));
        }

        [HttpGet]
        public IActionResult Get(string uid)//此处的ID为Guid
        {
            if (string.IsNullOrEmpty(uid))
                return BadRequest(new ActionStatus(-1, "参数异常"));
            Company compay = _compayContext.Companies.Where(s => s.Uid == uid).FirstOrDefault();
            if (compay == null)
                return NotFound(new ActionStatus(-1, "未检索到企业信息"));
            return Ok(new ActionStatus(200, "SUCCESS", compay));
        }


        [HttpPost]
        public async Task<IActionResult> Update(string uid, [FromForm] IFormCollection dict)
        {
            if (string.IsNullOrEmpty(uid))
                return BadRequest(new ActionStatus(-1, "参数异常"));

            Company compay = _compayContext.Companies.Where(s => s.Uid == uid).FirstOrDefault();

            if (compay == null)
                return NotFound(new ActionStatus(-1, "未检索到企业信息"));

            if(!ParseCompanyForm(ref compay, dict))
                return BadRequest(new ActionStatus(-1, "参数解析异常"));

            int len = await _compayContext.SaveChangesAsync();
            if(len > 0)
                return Ok(new ActionStatus(200, "信息更新成功"));
            else
                return BadRequest(new ActionStatus(-1, "内部错误：更新失败"));

        }
        #endregion

        #region 发布工作相关
        [HttpPost]
        public async Task<IActionResult> PublishJobs(string uid,  [FromForm] IFormCollection dict)
        {
            if(string.IsNullOrEmpty(uid))
                return BadRequest(new ActionStatus(-1, "参数异常"));

            var com = _compayContext.Companies.Where(s => s.Uid == uid).FirstOrDefault();
            if (com == null)
                return BadRequest(new ActionStatus(-1, "账号不存在"));

            if(com.CanPubJob != 1 )
                return BadRequest(new ActionStatus(-1, $"暂不能发布招聘信息，错误信息：{GlobalDefines.ZpShenHeStatusDic[com.CanPubJob]}"));
            TimeSpan ts = (TimeSpan)(DateTime.Today - com.PubJobDate);
            if (ts.TotalDays > 180)
            {
                com.CanPubJob = 0;
                await _compayContext.SaveChangesAsync();
                return BadRequest(new ActionStatus(-1, "申请已过期，请重新提交资料申请发布工作权限"));
            }

            Job job = new Job();
            if(!ParseJobForm(dict, ref job))
                return BadRequest(new ActionStatus(-1, "参数异常"));
            if(!CheckJobNotNull(job))
                return BadRequest(new ActionStatus(-1, "职位信息不完整"));

             _jobContext.Add(job);
            int len = await _jobContext.SaveChangesAsync();
            if(len > 0)
                return Ok(new ActionStatus(200, "发布成功", job.Id));
            else
                return BadRequest(new ActionStatus(-1, "内部错误，发布失败"));
        }

        [HttpGet]
        public IActionResult GetJob(string id)
        {
            if (string.IsNullOrEmpty(id))
                return BadRequest(new ActionStatus(-1, "参数异常", null));
            var jobs = _jobContext.Jobs.Where(s => s.Id == id).FirstOrDefault();
            if (jobs != null)
                return Ok(new ActionStatus(200, "查找成功", jobs));
            return NotFound(new ActionStatus(-1, "查找失败"));
        }

        [HttpGet]
        public IActionResult AllJobs(string companyId)
        {
            if (string.IsNullOrEmpty(companyId))
                return BadRequest(new ActionStatus(-1, "组织代号错误", null));

            var jobs = _jobContext.Jobs.Where(s => s.CompanyId == companyId);
            return Ok(new ActionStatus(200, "查找成功", jobs));
        }

        [HttpPost]
        public async Task<IActionResult> EditJob(string id, [FromForm] IFormCollection dict)
        {
            if (string.IsNullOrEmpty(id))
                return BadRequest(new ActionStatus(-1, "参数异常"));
            Job job = _jobContext.Jobs.Where(s => s.Id == id).FirstOrDefault();
            if (job == null)
                return NotFound(new ActionStatus(-1, "未查找到岗位"));

            if (!ParseJobForm(dict, ref job))
                return BadRequest(new ActionStatus(-1, "参数异常"));
            if (!CheckJobNotNull(job))
                return BadRequest(new ActionStatus(-1, "职位信息不完整"));

            int len = await _jobContext.SaveChangesAsync();
            if (len > 0)
                return Ok(new ActionStatus(200, "更新成功", job.Id));
            return BadRequest(new ActionStatus(-1, "内不错误，更新失败"));

        }


        private bool ParseJobForm(IFormCollection dict, ref Job job)
        {
            if (dict.Keys.Count == 0)
                return false;
            PropertyInfo[] pis = job.GetType().GetProperties();
            foreach (PropertyInfo pi in pis)
            {
                string name = pi.Name.ToLower();
                if (!dict.ContainsKey(pi.Name))
                    continue;
                var pValue = dict[name][0];
                if (string.IsNullOrEmpty(pValue))
                    continue;
                bool serverUpdate = pi.IsDefined(typeof(OnlyServerUpdateAttribute));
                if (serverUpdate)
                    continue;
                else if (pi.PropertyType.FullName.Contains("DateTime"))
                {
                    DateTime dt;
                    if (DateTime.TryParse(pValue, out dt))
                        pi.SetValue(job, dt, null);
                    else
                        return false;
                }
                else if (pi.PropertyType.FullName.Contains("Int32"))
                {
                    int v;
                    if (Int32.TryParse(pValue, out v))
                        pi.SetValue(job, v, null);
                    else
                        return false;
                }
                else if (pi.PropertyType.FullName.Contains("String"))
                {
                    pi.SetValue(job, pValue, null);
                }
            }
            job.UpdateTime = DateTime.Today;
            return true;
        }

        private bool CheckJobNotNull(Job job)
        {
            PropertyInfo[] pis = job.GetType().GetProperties();
            foreach (var pi in pis)
            {
                bool v = pi.IsDefined(typeof(AutoValueSetAttribute));
                var t  = pi.GetValue(job);
                if (v && (t == null))
                    return false;
            }
            return true;
        }

        [HttpPost]
        public async Task<IActionResult> DeleteJob(string id)
        {
            if (string.IsNullOrEmpty(id))
                return BadRequest(new ActionStatus(-1, "参数异常"));
            Job job = _jobContext.Jobs.Where(s => s.Id == id).FirstOrDefault();
            if (job == null)
                return NotFound(new ActionStatus(-1, "未查找到岗位"));
            else
            {
                _jobContext.Jobs.Remove(job);
                await _jobContext.SaveChangesAsync();
                return Ok(new ActionStatus(200, "操作成功"));
            }
        }

        #endregion

        #region 申请招聘权限
        [HttpPost]
        public async Task<IActionResult> UploadZZ(string uid, [FromForm]IFormCollection dict)
        {
            if (string.IsNullOrEmpty(uid))
                return BadRequest(new ActionStatus(-1, "参数异常"));

            var com = _compayContext.Companies.Where(s => s.Uid == uid).FirstOrDefault();
            if (com == null)
                return BadRequest(new ActionStatus(-1, "用户不存在", string.Empty));

            IFormFile photo = dict.Files["zz"];
            if (photo == null)
                return BadRequest(new ActionStatus(-1, "参数异常", string.Empty));


            string fileExten = Path.GetExtension(photo.FileName).ToLower();
            if (!GlobalDefines.ImgTypeDict.Keys.Contains(fileExten))
                return BadRequest(new ActionStatus(-1, "上传图片格式错误", string.Empty));

            string comPath = com.Name;
            if(string.IsNullOrEmpty( comPath))
                return BadRequest(new ActionStatus(-1, "公司名称错误，请完善企业信息", string.Empty));


            var dirPath = Path.Combine(_webHostEnvironment.ContentRootPath + GlobalDefines.ComPhotoPath + $"{comPath}\\");
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);
            string filePath = Path.Combine(dirPath, com.Uid+ "_zz" + Path.GetExtension(photo.FileName));

            using (var fs = System.IO.File.Create(filePath))
            {
                await photo.CopyToAsync(fs);
            }
            com.ZzPath = filePath;
            await _compayContext.SaveChangesAsync();
            return Ok(new ActionStatus(200, "上传成功", com.Uid));
        }

        [HttpPost]
        public async Task<IActionResult> UploadIdCard(string uid, [FromForm] IFormCollection dict)
        {
            if (string.IsNullOrEmpty(uid))
                return BadRequest(new ActionStatus(-1, "参数异常"));

            var com = _compayContext.Companies.Where(s => s.Uid == uid).FirstOrDefault();
            if (com == null)
                return BadRequest(new ActionStatus(-1, "用户不存在", string.Empty));

            IFormFile photo = dict.Files["IdCard"];
            if (photo == null)
                return BadRequest(new ActionStatus(-1, "参数异常", string.Empty));


            string fileExten = Path.GetExtension(photo.FileName).ToLower();
            if (!GlobalDefines.ImgTypeDict.Keys.Contains(fileExten))
                return BadRequest(new ActionStatus(-1, "上传图片格式错误", string.Empty));

            string comPath = com.Name;
            if (string.IsNullOrEmpty(comPath))
                return BadRequest(new ActionStatus(-1, "公司名称错误，请完善企业信息", string.Empty));


            var dirPath = Path.Combine(_webHostEnvironment.ContentRootPath + GlobalDefines.ComPhotoPath + $"{comPath}\\");
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);
            string filePath = Path.Combine(dirPath, com.Uid + "_IdCard" + Path.GetExtension(photo.FileName));

            using (var fs = System.IO.File.Create(filePath))
            {
                await photo.CopyToAsync(fs);
            }
            com.IdCardPath = filePath;
            await _compayContext.SaveChangesAsync();
            return Ok(new ActionStatus(200, "上传成功", com.Uid));
        }

        [HttpPost]
        public async Task<IActionResult> UploadSq(string uid, [FromForm] IFormCollection dict)
        {
            if (string.IsNullOrEmpty(uid))
                return BadRequest(new ActionStatus(-1, "参数异常"));

            var com = _compayContext.Companies.Where(s => s.Uid == uid).FirstOrDefault();
            if (com == null)
                return BadRequest(new ActionStatus(-1, "用户不存在", string.Empty));

            IFormFile photo = dict.Files["Sq"];
            if (photo == null)
                return BadRequest(new ActionStatus(-1, "参数异常", string.Empty));


            string fileExten = Path.GetExtension(photo.FileName).ToLower();
            if (!GlobalDefines.ImgTypeDict.Keys.Contains(fileExten))
                return BadRequest(new ActionStatus(-1, "上传图片格式错误", string.Empty));

            string comPath = com.Name;
            if (string.IsNullOrEmpty(comPath))
                return BadRequest(new ActionStatus(-1, "公司名称错误，请完善企业信息", string.Empty));


            var dirPath = Path.Combine(_webHostEnvironment.ContentRootPath + GlobalDefines.ComPhotoPath + $"{comPath}\\");
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);
            string filePath = Path.Combine(dirPath, com.Uid + "_Sq" + Path.GetExtension(photo.FileName));

            using (var fs = System.IO.File.Create(filePath))
            {
                await photo.CopyToAsync(fs);
            }
            com.SqPath = filePath;
            await _compayContext.SaveChangesAsync();
            return Ok(new ActionStatus(200, "上传成功", com.Uid));
        }
        
        [HttpPost]                
        public async Task<IActionResult> SqPubJob(string uid)
        {
            if (string.IsNullOrEmpty(uid)) return BadRequest(new ActionStatus(-1, "参数异常"));

            var com = _compayContext.Companies.Where(s=>s.Uid ==  uid).FirstOrDefault();
            if (com == null) return Ok(new ActionStatus(-1, "用户不存在"));

            if (string.IsNullOrEmpty(com.ZzPath) ||
               string.IsNullOrEmpty(com.SqPath) ||
               string.IsNullOrEmpty(com.IdCardPath))
                return Ok(new ActionStatus(-1, "请补全申请材料后重试"));
            else
            {
                RecruitmentApplication ra = new RecruitmentApplication(com.Name, com.CompanyId);
                await _raCxt.RAs.AddAsync(ra);
                int line = await _raCxt.SaveChangesAsync();
                com.CanPubJob = 3;
                _compayContext.SaveChangesAsync();
                if (line > 0)
                    return Ok(new ActionStatus(200, "已提交申请,请等待审核", ra.Uid));
                else
                    return BadRequest(new ActionStatus(500, "Server Error，Try Again", ra.Uid));
            }
        }
        #endregion

        [HttpGet]
        public IActionResult GenderStatistics(string cid)
        {
            if (string.IsNullOrEmpty(cid)) return BadRequest(new ActionStatus(-1, "参数异常"));
            var fiveYearAgo = DateTime.Now.AddYears(-5);
            var rs = _resumeCxt.Resumes.Where(s=>s.CompanyId.Equals(cid) && s.BeginTime>fiveYearAgo).ToList().OrderByDescending(s=>s.BeginTime).DistinctBy(s=>s.CitizenId).ToList();//&& ((TimeSpan)(DateTime.Today - s.BeginTime)).TotalDays <= 365*5 
            var ids = rs.Select(s => s.CitizenId);

            var stus = _stuCxt.Students.Where(s => ids.Contains(s.CitizenId));
            int maleCnt = stus.Count(s => s.Gender == GlobalDefines.GenderMale);
            int femaleCnt = stus.Count(s => s.Gender == GlobalDefines.GenderFemale);
            JsonObject js = new JsonObject
            {
                ["maleCnt"] = maleCnt,
                ["femaleCnt"] = femaleCnt
            };
            return Ok(new ActionStatus(200, "查询成功", js ));
        }

        [HttpGet]
        public IActionResult MajorStatistics(string cid)
        {
            if (string.IsNullOrEmpty(cid)) return BadRequest(new ActionStatus(-1, "参数异常"));
            var fiveYearAgo = DateTime.Now.AddYears(-5);
            var rs = _resumeCxt.Resumes.Where(s => s.CompanyId.Equals(cid) && s.BeginTime > fiveYearAgo).ToList().OrderByDescending(s => s.BeginTime).DistinctBy(s => s.CitizenId).ToList();//&& ((TimeSpan)(DateTime.Today - s.BeginTime)).TotalDays <= 365*5             
            var ids = rs.Select(s => s.CitizenId);
            var stus = _stuCxt.Students.Where(s => ids.Contains(s.CitizenId));//近五年的学生

            var majors = stus.Select(s => s.Major).Where(s=>s!=null).Distinct().ToArray();
            //Dictionary<string, int> majorCntDic = new Dictionary<string, int>();

            JsonArray ja = new JsonArray();
            var uds = _udCxt.UniversityDivisions.ToList();
            for (int i = 0; i < majors.Length; i++)
            {
                int cnt = stus.Count(s => s.Major == majors[i]);
                var ud = uds.Where(s => $"{s.Id}" == majors[i]).FirstOrDefault();
                if (ud == null)
                    continue;
                var majorName = ud.Name;
                JsonObject item = new JsonObject
                {
                    [$"{majorName}"] = cnt,
                };
                ja.Add(item);

                //majorCntDic.Add(majors[i], cnt);
            }       
            return Ok(new ActionStatus(200, "查询成功", ja));
        }

        [HttpGet]
        public IActionResult CntYear(string cid)
        {
            if (string.IsNullOrEmpty(cid)) return BadRequest(new ActionStatus(-1, "参数异常"));
            //Dictionary<string, int> yearCnt = new Dictionary<string, int>();
            JsonArray ja = new JsonArray();

            int year = DateTime.Now.Year;
            var YearAgo1 = DateTime.Parse($"{year}-1-1");
            var YearAgo2 = DateTime.Parse($"{year-1}-1-1");
            var YearAgo3 = DateTime.Parse($"{year-2}-1-1");
            var YearAgo4 = DateTime.Parse($"{year-3}-1-1");
            var YearAgo5 = DateTime.Parse($"{year-4}-1-1");
            int one =   _resumeCxt.Resumes.Where(s => s.CompanyId.Equals(cid) && s.BeginTime >= YearAgo1).ToList().DistinctBy(s => s.CitizenId).Count();//&& ((TimeSpan)(DateTime.Today - s.BeginTime)).TotalDays <= 365*5             
            int two =   _resumeCxt.Resumes.Where(s => s.CompanyId.Equals(cid) && s.BeginTime >= YearAgo2 && s.BeginTime < YearAgo1).ToList().DistinctBy(s => s.CitizenId).Count();//&& ((TimeSpan)(DateTime.Today - s.BeginTime)).TotalDays <= 365*5             
            int three = _resumeCxt.Resumes.Where(s => s.CompanyId.Equals(cid) && s.BeginTime >= YearAgo3 && s.BeginTime < YearAgo2).ToList().DistinctBy(s => s.CitizenId).Count();//&& ((TimeSpan)(DateTime.Today - s.BeginTime)).TotalDays <= 365*5             
            int four =  _resumeCxt.Resumes.Where(s => s.CompanyId.Equals(cid) && s.BeginTime >= YearAgo4 && s.BeginTime < YearAgo3).ToList().DistinctBy(s => s.CitizenId).Count();//&& ((TimeSpan)(DateTime.Today - s.BeginTime)).TotalDays <= 365*5             
            int five =  _resumeCxt.Resumes.Where(s => s.CompanyId.Equals(cid) && s.BeginTime >= YearAgo5 && s.BeginTime < YearAgo4).ToList().DistinctBy(s => s.CitizenId).Count();//&& ((TimeSpan)(DateTime.Today - s.BeginTime)).TotalDays <= 365*5             
            JsonObject ja1 = new JsonObject
            {
                [$"{DateTime.Now.Year}"] = one
            };
            JsonObject ja2 = new JsonObject
            {
                [$"{DateTime.Now.Year-1}"] = two
            };
            JsonObject ja3 = new JsonObject
            {
                [$"{DateTime.Now.Year-2}"] = three
            };
            JsonObject ja4 = new JsonObject
            {
                [$"{DateTime.Now.Year-3}"] = four
            };
            JsonObject ja5 = new JsonObject
            {
                [$"{DateTime.Now.Year-4}"] = five
            };

            //yearCnt.Add($"{DateTime.Now.Year}", one);
            //yearCnt.Add($"{DateTime.Now.Year - 1}", two);
            //yearCnt.Add($"{DateTime.Now.Year - 2}", three);
            //yearCnt.Add($"{DateTime.Now.Year - 3}", four);
            //yearCnt.Add($"{DateTime.Now.Year - 4}", five);
            ja.Add(ja1);
            ja.Add(ja2);
            ja.Add(ja3);
            ja.Add(ja4);
            ja.Add(ja5);
            return Ok(new ActionStatus(200, "查询成功", ja));
        }
    }
}
